home *** CD-ROM | disk | FTP | other *** search
- // 3D Rotation Program 3D_2.CPP
-
- // adding edge class
-
- // 18/12/94
- #define version "1.09"
-
- // sine angle lookup table added (floating point)
- // transformation data read from data file
- // calculates surface normals from shading
- // support for OFF files via FILTER2 added
-
-
-
- #include "3d_2a.h"
-
-
- // prototypes
-
- void read_absolute_coords(char name[], surface *s_ptr, vector *v_ptr);
- void draw(surface *s_ptr, vector *e_ptr, int line_remove);
- void hidden_face_remove(matrix m_ptr, surface *s_ptr, vector *v_ptr);
- void image_clear(int x, int y);
- void convert_vertex_eye(matrix matr, vector *v_ptr, vector *e_ptr);
- void get_filename(char *file_name);
- void fast_kbflush(void);
- void grey_16_palette(void);
-
-
-
- main(int argc, char *argv[])
- {
- int hidden_line_removal = true;
- int redraw = false;
- matrix view;
- clock_t start, stop;
-
- if (argc!=2)
- {
- cout << "\nRotates a 3D object.\n3D_2 [datafile._3d]\n";
- exit(1);
- }
-
- char file_name[80];
- strcpy(file_name, argv[1]);
- get_filename(&file_name[0]); // get the file name
-
- ifstream in(file_name);
- // if cann't open file then exit
- if (!in)
- {
- cout << "Cannot open file " << file_name;
- exit(1);
- }
-
- in >> no_of_vertices;
- in >> no_of_surfaces;
-
- vector *vertex, *eye_vertex;
- surface *surf;
-
- vertex = new vector[no_of_vertices];
- eye_vertex = new vector[no_of_vertices];
- surf = new surface[no_of_surfaces];
-
- if (!surf || !vertex || !eye_vertex)
- {
- cout << "Allocation error\n";
- exit(1);
- }
-
-
- read_absolute_coords(file_name, surf, vertex);
-
-
- // goto graphics mode
- int driver = VGA;
- int mode = VGAHI;
- initgraph(&driver, &mode, "");
- int errorcode;
- errorcode = graphresult();
- if (errorcode != grOk)
- {
- cout << "Graphics error: " << grapherrormsg(errorcode) << "\n";
- exit(1);
- }
-
- setcolor(WHITE);
- int x_max, y_max;
- x_max = getmaxx();
- y_max = getmaxy();
- grey_16_palette();
-
- // calculate transformation matrix
- view.calculate();
-
- // calculate normal vectors
- for(int surfaceno=0; surfaceno<no_of_surfaces; surfaceno++)
- {
- surf[surfaceno].calculate_normal(vertex);
- }
-
- hidden_face_remove(view, surf, vertex);
- convert_vertex_eye(view, vertex, eye_vertex);
- draw(surf, eye_vertex, hidden_line_removal);
-
-
- int ch;
- do
- {
- ch = getch();
- if (ch==0) ch = getch() + 256;
- fast_kbflush();
- redraw = false;
-
- switch (ch)
- {
- case 328:
- view.set_phi(5);
- redraw = true;
- break;
- case 336: //
- view.set_phi(-5);
- redraw = true;
- break;
- case 333: // 'right' arrow key
- view.set_theta(5);
- redraw = true;
- break;
- case 331: // 'left' arrow key
- view.set_theta(-5);
- redraw = true;
- break;
- case 45: // '+' key
- view.set_rho(20);
- redraw = true;
- break;
- case 43: // '-' key
- view.set_rho(-20);
- redraw = true;
- break;
- case 104: // 'h' key
- // if hidden line removal on then turn off, and vice-versa
- hidden_line_removal = hidden_line_removal ? false : true;
- redraw = true;
- break;
- default:
- break;
- }
- if (redraw)
- {
- // remove old image
- image_clear(x_max, y_max);
-
- // draw new image
- start = clock();
- view.calculate();
- if (hidden_line_removal) hidden_face_remove(view, surf, vertex);
- convert_vertex_eye(view, vertex, eye_vertex);
- draw(surf, eye_vertex, hidden_line_removal);
- stop = clock();
- }
- } while (ch != 113); // 'q' key
-
-
- // return back to dos
- restorecrtmode();
- cout << "\n3D Rotation program version " << version << "\n";
- cout << "Compiled on " << __DATE__ << " at " << __TIME__ << "\n";
- printf("The time was: %f\n", (stop - start) / CLK_TCK);
- exit(0);
- }
-
-
- void draw(surface *s_ptr, vector *e_ptr, int line_remove)
- {
- float xe,ye,ze;
- int xs,ys;
- int q, p, *poly, num;
-
- int screendist = 2000;
- int surfaceno;
-
- for(surfaceno=0; surfaceno<no_of_surfaces; surfaceno++)
- {
- // if visible draw surface or if hidden line removal off
- if ((s_ptr[surfaceno].get_visible()) || (!line_remove))
- {
- num = s_ptr[surfaceno].get_no_of_verts();
- p = (num*2)+2;
- poly = new int[p];
- if (!poly) exit(1);
-
- int j;
-
- for(j=0; j<s_ptr[surfaceno].get_no_of_verts(); j++)
- {
- q = s_ptr[surfaceno].get_vert(j);
-
- xe = e_ptr[q].get_x();
- ye = e_ptr[q].get_y();
- ze = e_ptr[q].get_z();
-
- xs = screendist * (xe / ze);
- ys = screendist * (ye / ze);
-
- if (!j)
- {
- poly[(num*2)] = xs + origin_x;
- poly[(num*2)+1] = ys + origin_y;
- //moveto (xs + origin_x, ys + origin_y);
- }
-
- poly[j*2] = xs + origin_x;
- poly[(j*2)+1] = ys + origin_y;
- }
-
- if (!line_remove) drawpoly((p/2), poly);
- else
- {
- setfillstyle(SOLID_FILL, s_ptr[surfaceno].get_shading());
- fillpoly((p/2),poly);
- }
-
- delete [p] poly;
- }
- }
- }
-
-
-
-
- // initialise the arrays
- void read_absolute_coords(char name[], surface *s_ptr, vector *v_ptr)
- {
- int no,x,y,z;
- char ch;
-
- ifstream in(name);
- // if cann't open file then exit
- if (!in)
- {
- exit(1);
- }
-
- cout << "Reading data file " << name << "\n";
-
-
- int tmp_num;
- in >> tmp_num; // find no. of vertices
- in >> tmp_num; // find no. of surfaces
- in >> tmp_num; // total no. of vertices & surfaces
-
-
- for(int i=0; i<no_of_vertices; i++)
- {
- in >> x;
- in >> y;
- in >> z;
- v_ptr[i].assign(x,y,z);
- }
-
- int vertice;
- int vert[9];
- for(i=0; i<no_of_surfaces; i++)
- {
- in >> vertice;
- if (vertice > 8)
- {
- cout << "\nAt present can only a max. of 8 vertices to a surface\n";
- exit(1);
- }
- s_ptr[i].init_vert(vertice);
- for(int j=0; j<vertice; j++)
- {
- in >> vert[j];
- if (vert[j] < 0)
- {
- cout << "\nVertex number is -ve\n";
- exit(1);
- }
- }
- s_ptr[i].set_vert(vert);
- }
-
- in.close();
- }
-
-
-
- void hidden_face_remove(matrix m_ptr, surface *s_ptr, vector *v_ptr)
- {
- vector view;
- {
- float sin_phi;
- int theta, phi, rho;
-
- theta = m_ptr.get_theta();
- phi = m_ptr.get_phi();
- rho = m_ptr.get_rho();
-
- sin_phi = f_sin(phi);
-
- long v1,v2,v3;
- v1 = rho * sin_phi * f_cos(theta);
- v2 = rho * sin_phi * f_sin(theta);
- v3 = rho * f_cos(phi);
- view.assign(v1,v2,v3);
- }
-
- int surfaceno, t0;
- vector los;
-
- for (surfaceno=0; surfaceno<no_of_surfaces; surfaceno++)
- {
- // calculate line of sight vectors
- t0 = s_ptr[surfaceno].get_vert(0);
- los = view - v_ptr[t0];
-
- // is it visible ?
- //s_ptr[surfaceno].calculate_visibility(los);
- s_ptr[surfaceno].calculate_shading(los);
- }
- }
-
- // clears the image
- void image_clear(int x, int y)
- {
- int box[] = {0,0, 0,y+1, x,y+1, x,0};
- int color;
- color = getcolor();
- setcolor(BLACK);
- setfillstyle(SOLID_FILL, BLACK);
- fillpoly(4,box);
- setcolor(color);
- }
-
-
- // converts the world co-ordinates into eye co-ordinates
- void convert_vertex_eye(matrix matr, vector *v_ptr, vector *e_ptr)
- {
- vector temp;
-
- for(int vertexno=0; vertexno<no_of_vertices; vertexno++)
- {
- temp.assign(v_ptr[vertexno]);
-
- // multiply vector with matrix
- temp = temp * (matr);
-
- e_ptr[vertexno].assign(temp);
- }
- }
-
- // set the 16 colour palette to 15 shades of grey
- void grey_16_palette(void)
- {
- register int j;
- struct palettetype pal;
-
- // load the colour palette with the 15 shades of grey
- getpalette (&pal);
-
- for (j=0; j<pal.size; j++)
- setrgbpalette (pal.colors[j], j*4, j*4, j*4);
- }
-
-
- void fast_kbflush(void)
- {
- *((unsigned far *)MK_FP(0x40, 0x1a)) = *((unsigned far *)MK_FP(0x40, 0x1c));
- }
-
-
- // append a ._3d to the file name
- void get_filename(char *file_name)
- {
- char drive[3];
- char dir[66];
- char fname[9];
- char file[9];
- char ext[5];
- int flag;
-
- flag = fnsplit(file_name, drive, dir, fname, ext);
- if (flag & WILDCARDS)
- {
- cout << "Wildcard found in file name.\n";
- exit(1);
- }
-
- if (!(flag & FILENAME))
- {
- cout << "A file name is required!\n";
- exit(1);
- }
-
- getcwd(file_name,MAXPATH); // get current directory
- strcat(file_name,"\\"); // append a trailing \
- fnsplit(file_name,drive,dir,file,ext);
- strupr(fname);
- strcpy(file,fname);
- strcpy(ext,"._3D");
- // read file from the current dir
- fnmerge(file_name,drive,dir,file,ext);
- }